package es.unileon.rnag.jgen.ejemplos;

import java.util.ArrayList;
import java.util.List;

import es.unileon.rnag.jgen.AlgoritmoGenetico;
import es.unileon.rnag.jgen.Cromosoma;
import es.unileon.rnag.jgen.Estrategia;
import es.unileon.rnag.jgen.genes.Gen;
import es.unileon.rnag.jgen.genes.GenLista;
import es.unileon.rnag.jgen.genes.GenRango;
import es.unileon.rnag.jgen.operadores.Parada;

public class Biotec04_0411 extends Cromosoma {

	static String[] cadena = {"H","P","P","H","H","P","H","P","P","H","H","H","P","P"};
	static String[] valores = {"L", "R", "LU", "LD", "RU", "RD"};
	public Biotec04_0411(){
		super(cadena.length-1);
		List<Integer> listaValores = new ArrayList<Integer>();
		listaValores.add(1);
		listaValores.add(2);
		listaValores.add(3);
		listaValores.add(4);
		listaValores.add(5);
		listaValores.add(6);
		for (int i=0; i<cadena.length-1; i++){
			addGen(new GenLista<Integer>(listaValores));
		}
	}
	public Biotec04_0411(Cromosoma c) {
		super(c);
	}
	
	protected double calcularAptitud(){
		Gen[] genes = getGenes();
		double apt = 0;
		boolean coinciden = false;
		int[] coordenadaX = new int[cadena.length];
		coordenadaX[0] = 0;
		int[] coordenadaY = new int[cadena.length];
		coordenadaY[0] = 0;
		for (int i=1; i<cadena.length; i++){
			if ((Integer)genes[i-1].getValor() == 1){
				coordenadaX[i] = coordenadaX[i-1] - 1;
				coordenadaY[i] = coordenadaY[i-1];
			}
			if ((Integer)genes[i-1].getValor() == 2){
				coordenadaX[i] = coordenadaX[i-1] + 1;
				coordenadaY[i] = coordenadaY[i-1];
			}
			if ((Integer)genes[i-1].getValor() == 3){
				coordenadaX[i] = coordenadaX[i-1] - 1;
				coordenadaY[i] = coordenadaY[i-1] + 1;
			}
			if ((Integer)genes[i-1].getValor() == 4){
				coordenadaX[i] = coordenadaX[i-1];
				coordenadaY[i] = coordenadaY[i-1] - 1;
			}
			if ((Integer)genes[i-1].getValor() == 5){
				coordenadaX[i] = coordenadaX[i-1];
				coordenadaY[i] = coordenadaY[i-1] + 1;
			}
			if ((Integer)genes[i-1].getValor() == 6){
				coordenadaX[i] = coordenadaX[i-1] + 1;
				coordenadaY[i] = coordenadaY[i-1] - 1;
			}
		}
		for(int i = 0; i < cadena.length; i++){
			for(int j = i+1; j < cadena.length; j++){
				if((coordenadaX[i]==coordenadaX[j])&&(coordenadaY[i]==coordenadaY[j])){
					coinciden=true;
				}
			}
		}
		if ((cadena[0].equals("H")) && (cadena[1].equals("H"))){
			for (int i=2; i<cadena.length; i++){
				if ((Math.abs(coordenadaX[i]) <= 1) && (Math.abs(coordenadaY[i]) <= 1)){
					apt--;
				}	
			}
		}
		
		
		for (int i=1; i<cadena.length; i++){
			if (cadena[i] == "H"){
				if ((cadena[i-1] == "H") || (cadena[i+1] == "H")){
					for (int j=0; j<i; j++){
						if ((coordenadaX[j] - coordenadaX[i] <=1) && (Math.abs(coordenadaY[j] - coordenadaY[i]) <= 1)){
							apt--;
						}
					}
					for (int j = i+2; j<cadena.length; j++){
						if ((Math.abs(coordenadaX[j] - coordenadaY[i]) <= 1) && (Math.abs(coordenadaY[j] - coordenadaX[j]) <= 1)){
							apt--;
						}
					}
				}
			}
		}
		if ((cadena[cadena.length - 2] == "H") && (cadena[cadena.length-1] == "H")){
			for (int i=0; i < cadena.length-1; i++){
				if ((Math.abs(coordenadaX[i] - coordenadaX[cadena.length-1]) <=1) && (Math.abs(coordenadaY[i] - coordenadaY[cadena.length-1]) <= 1)){
					apt--;
				}
			}
		}
		if(coinciden){
			apt+=50000;
		}
		return -apt;
	}
	
	static class CondicionParada implements Parada{
		double[] aptitudesAnteriores = new double[5];
		{
			for(int i = 0; i < aptitudesAnteriores.length; i++){
				aptitudesAnteriores[i]=0.0;
			}
		}
		@Override
		public boolean comprobarParada(List<Cromosoma> poblacion, int generacion) {
			aptitudesAnteriores[generacion%aptitudesAnteriores.length] = poblacion.get(0).getAptitud();
			if(generacion>=aptitudesAnteriores.length){
				boolean iguales = true;
				for(int i = 0; i < aptitudesAnteriores.length-1; i++){
					iguales &= aptitudesAnteriores[i]==aptitudesAnteriores[i+1];
				}
				return iguales;
			}
			return false;
		}
		
	}
	
	public static void main(String[] args) {
		Estrategia e = new Estrategia(Estrategia.RULETA_DOS_PUNTOS, 0.8f,0.4f);
		AlgoritmoGenetico ag = new AlgoritmoGenetico(Biotec04_0411.class, e, new CondicionParada(), 50, 200);
		ag.evolucionar();
		Cromosoma mejor = ag.getMejor();
		Gen[] genes = mejor.getGenes();
		System.out.print("La mejor disposicion es: " + valores[(Integer)genes[0].getValor()-1]);
		for(int i = 1; i < genes.length; i++){
			System.out.print(" - " + valores[(Integer)genes[i].getValor()-1]);
		}
		System.out.println();
		System.out.println("La energia libre de Gibbs es: " + -mejor.getAptitud());
	}	
}
